package com.redoor.app.stake.basicdata.hsf.service.impl;

import com.alibaba.boot.hsf.annotation.HSFProvider;
import com.alibaba.fastjson.JSON;
import com.redoor.app.stake.auth.model.BaseUserView;
import com.redoor.app.stake.auth.service.BaseUserService;
import com.redoor.app.stake.basicdata.aop.IgnoreAopLog;
import com.redoor.app.stake.basicdata.commons.BasicDataStatus;
import com.redoor.app.stake.basicdata.hsf.service.utils.CommonUtil;
import com.redoor.app.stake.basicdata.model.*;
import com.redoor.app.stake.basicdata.model.constants.BasePropConstants;
import com.redoor.app.stake.basicdata.model.constants.BasicDataRedisConstants;
import com.redoor.app.stake.basicdata.model.controllerModel.BaseChargerfeemodelCriteria;
import com.redoor.app.stake.basicdata.model.controllerModel.BasePropCriteria;
import com.redoor.app.stake.basicdata.model.controllerModel.BaseServicefeemodelCriteria;
import com.redoor.app.stake.basicdata.model.controllerModel.BaseStakeCriteria;
import com.redoor.app.stake.basicdata.mq.sendService.SendMQService;
import com.redoor.app.stake.basicdata.service.*;
import com.redoor.app.stake.common.service.RedisService;
import com.redoor.app.stake.common.utils.UUIDTool;
import com.yotouch.app.stake.Consts;
import com.yotouch.app.stake.StakeConsts;
import com.yotouch.app.stake.hsf.StakeService;
import com.yotouch.app.stake.hsf.StationService;
import com.yotouch.app.stake.model.Registration;
import com.yotouch.app.stake.model.RegistrationApply;
import com.yotouch.app.stake.model.Stake;
import com.yotouch.app.stake.model.response.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Transactional

@HSFProvider(serviceInterface = StakeService.class, serviceVersion = "5.0.0", serviceGroup = "grp_asset_of_stake", clientTimeout = 600000)
public class StakeServiceImpl implements StakeService {

    private static final Logger logger = LoggerFactory.getLogger(StakeServiceImpl.class) ;

    @Autowired
    private BaseStakeService baseStakeService;

    @Autowired
    private BaseChargerService baseChargerService;

    @Autowired
    private SyncOrganizationService syncOrganizationService;

    @Autowired
    private BaseUserService baseUserService;

    @Autowired
    private SyncChargerFeeModelService chargerfeemodelService;

    @Autowired
    private SyncServiceFeeModelService servicefeemodelService;

    @Autowired
    private BaseRegistrationApplyService baseRegistrationApplyService;

    @Autowired
    private BaseRegistrationService baseRegistrationService;

    @Autowired
    private BaseVendorInfoService baseVendorInfoService;

    @Autowired
    private BaseEquipmentInfoService baseEquipmentInfoService;

    @Autowired
    private BasePropService basePropService;

    @Autowired
    private BasePropRedisService basePropRedisService;

    @Autowired
    private BaseStakeOrgIndexService baseStakeOrgIndexService;

    @Autowired
    private BaseFeeModelRelService baseFeeModelRelService;

    @Autowired
    private CommonUtil commonUtil;

    @Autowired
    private SendMQService mqService;

    @Autowired
    RedisService redisService;

    @Autowired
    RegistrationApplyRedisService registrationApplyRedisService;

    /**
     * 统计国网桩数量
     * 互联互通调用
     *
     * @return
     */
    public ResponseInt sgccTotalCount() {

        ResponseInt ri = new ResponseInt(0, "") ;

        BaseStakeCriteria criteria = new BaseStakeCriteria();
        criteria.setIsthirds(BasicDataRedisConstants.THIRD_SGCC);
        criteria.setStakestatus(3);
        int res = baseStakeService.queryStakeCountHSF(criteria);
        ri.setValue(res);
        return ri ;
    }

    /**
     * 获取国网桩列表,只返回运行状态的桩
     * 互联互通调用
     *
     * @return
     */
    public ResponseStakeList sgccList(int offset, int limit){
        ResponseStakeList rsl = new ResponseStakeList(0, "") ;
        if(limit > 100){
            rsl.setErrMsg("get sgcc stake limit too large " + limit + ", set default 100") ;
            logger.debug("get sgcc stake limit too large " + limit + ", set default 100"); ;
            limit = 100 ;
        }

        BaseStakeCriteria criteria = new BaseStakeCriteria();
        criteria.setIsthirds(BasicDataRedisConstants.THIRD_SGCC);
        criteria.setStakestatus(3);
        criteria.setLimit(limit);
        criteria.setOffset(offset);

        List<Stake> stakes = baseStakeService.queryStakeHSF(criteria);
        rsl.setStakeList(stakes);

        return rsl ;
    }

    /**
     * 统计充电桩数量
     * 未发现调用方
     * @return
     */
    @Override
    public ResponseInt totalCount() {
        ResponseInt ri = new ResponseInt(0, "");

        BaseStakeCriteria criteria = new BaseStakeCriteria();
        int res = baseStakeService.queryStakeCountHSF(criteria);
        ri.setValue(res);
        return ri;
    }

    /**
     * 前置系统调用
     *
     * 获取充电桩数据
     *
     * @param offset
     * @param limit
     * @return
     */
    @Override
    public ResponseStakeList list(int offset, int limit) {
        ResponseStakeList rsl = new ResponseStakeList(0, "");
        logger.debug("in hsf stake service , list stake offset=" + offset + " limit=" + limit); ;
        if(limit > 100){
            rsl.setErrMsg("get stake size too large , set default size 100 ") ;
            logger.debug("get stake size too large " + limit); ;
            limit = 100 ;
        }

        BaseStakeCriteria criteria = new BaseStakeCriteria();
        criteria.setLimit(limit);
        criteria.setOffset(offset);

        List<Stake> stakes = baseStakeService.queryStakeHSF(criteria);
        rsl.setStakeList(stakes);
        return rsl;
    }

    /**
     * 统计充电站里充电桩数量
     *
     * @param stationUuid
     * @return
     */
    @Override
    public ResponseInt countByStation(String stationUuid) {
        ResponseInt ri = new ResponseInt(0, "");

        BaseStakeCriteria criteria = new BaseStakeCriteria();
        criteria.setStationuuid(stationUuid);
        int res = baseStakeService.queryStakeCountHSF(criteria);
        ri.setValue(res);
        return ri;
    }

    /**
     * 根据站ID查询桩列表
     * @param stationUuid 充电站主键
     * @param offset
     * @param count
     * @return
     */
    @Override
    public ResponseStakeList listByStation(String stationUuid, int offset, int count) {
        ResponseStakeList rsl = new ResponseStakeList(0, "");

        BaseStakeCriteria criteria = new BaseStakeCriteria();
        criteria.setLimit(count);
        criteria.setOffset(offset);
        criteria.setStationuuid(stationUuid);

        List<Stake> stakes = baseStakeService.queryStakeHSF(criteria);
        rsl.setStakeList(stakes);
        return rsl;        
    }

    /**
     * 根据充电桩 uuid 获取充电桩
     * 易充电调用
     * 科东调用
     * @param uuid
     * @return
     */
    @Override
    public ResponseStake get(String uuid) {
        logger.info("根据UUID查找桩信息："+uuid);
        try{
            ResponseStake rs = new ResponseStake(0, "");

            BaseStakeCriteria criteria = new BaseStakeCriteria();
//            criteria.setLimit(1);
//            criteria.setOffset(0);
            criteria.setUuid(uuid);

            Stake stake = baseStakeService.getStakeHSF(criteria);

            rs.setStake(stake);

            logger.info("查找到的桩信息："+ JSON.toJSONString(rs));
            return rs;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 申请桩注册码
     *
     * @param count - 注册码数量
     * @param type - 充电桩类型（直流，交流）
     * @param prOrgCode - 产权单位编码
     * @param chargerFeeModelId
     * @param serviceFeeModelId
     * @param note - 申请备注
     * @param orderId - 订单 id
     * @param vendorName - 生产厂家  //TODO 运维未传
     * @param equipModel - 设备型号 //TODO 运维未传
     * @param userToken - 用户 token
     * @return
     */
    @Override
    public ResponseBase genRegisterCode(
            int count,
            int type,
            String prOrgCode,
            String chargerFeeModelId, 
            String serviceFeeModelId, 
            String note, 
            String orderId, 
            String vendorName,
            String equipModel,
            String userName,
            String userToken ) {
        try{
            BaseUserView user = new BaseUserView();
            /*判断是否是本地运行,不是本地则发送mq.[该值来自于base_prop.isLocal字段]*/
            if (basePropService.isLocal()){
                user.setUuid(userToken);
            }else {
                /*通过接口验证用户是否存在 && 存在的话新增或者更新到数据库*/
                user = baseUserService.buildUserinfo(userToken);
                if(user == null){
                    //  错误代码：40013  错误内容：没有对应用户
                    return new ResponseBase(HsfError.ERROR_CODE_NO_SUCH_USER, HsfError.ERROR_MSG_NO_SUCH_USER) ;
                }
            }

            //验证组织机构
            SyncOrganization syncOrganization = syncOrganizationService.get(prOrgCode);
            if (syncOrganization == null){
                return new ResponseBase(HsfError.ERROR_CODE_NO_SUCH_ORG, HsfError.ERROR_MSG_NO_SUCH_ORG) ;
            }

            // 验证电费计费模型 TODO 改为调用清分接口直接校验
            BaseChargerfeemodelCriteria chargerfeemodelCriteria = new BaseChargerfeemodelCriteria();
            chargerfeemodelCriteria.setId(chargerFeeModelId);
            List<SyncChargerFeeModel> chargerfeemodels = chargerfeemodelService.queryChargerFeeModel(chargerfeemodelCriteria);
            SyncChargerFeeModel chargerfeemodel = (chargerfeemodels!=null && chargerfeemodels.size()>0)?chargerfeemodels.get(0):null;

            //验证服务费模型 TODO 改为调用清分接口直接校验
            BaseServicefeemodelCriteria servicefeemodelCriteria = new BaseServicefeemodelCriteria();
            servicefeemodelCriteria.setId(serviceFeeModelId);
            List<SyncServiceFeeModel> servicefeemodels = servicefeemodelService.queryServiceFeeModel(servicefeemodelCriteria);
            SyncServiceFeeModel servicefeemodel = (servicefeemodels!=null && servicefeemodels.size()>0)?servicefeemodels.get(0):null;

            if (chargerfeemodel == null || servicefeemodel == null){
                //  错误代码：40072  错误内容：没有对应的计费模型
                return new ResponseBase(HsfError.ERROR_CODE_NO_SUCH_FEEMODEL, HsfError.ERROR_MSG_NO_SUCH_FEEMODEL) ;
            }

            /*****  begin 功能描述：如果登录人的组织机构是部门级别的，查找他的地市级别的组织机构编码 产权单位只能到省市级别 zz  add 2017-12-17 *****/
            String ouCode = prOrgCode;
            if (ouCode.length() == 13){
                //根据组织编码获取地市级别的父实体 的组织编码
                SyncOrganization cityOrg = syncOrganizationService.get(syncOrganization.getParentorgno());
                if(cityOrg == null){
                    return new ResponseBase(HsfError.ERROR_CODE_NO_SUCH_ORG, HsfError.ERROR_MSG_NO_SUCH_ORG) ;
                }
                String tempOrg = cityOrg.getOrgno();
                ouCode = ("-1".equals(tempOrg) || StringUtils.isEmpty(tempOrg)) ? ouCode : tempOrg ;
            }
            /*****  end 功能描述：如果登录人的组织机构是部门级别的，查找他的地市级别的组织机构编码 zz  add 2017-12-17 *****/

            /*****begin 功能描述:将 注册码申请信息保存到redis里面  author:zhangMumu edit 2018/4/3 0003 11:27*****/

            RegistrationApplyForRedis registrationApplyForRedis = new RegistrationApplyForRedis();
            registrationApplyForRedis.setUuid(UUIDTool.getUUID());
            registrationApplyForRedis.setCount(count); //注册码申请数量
            registrationApplyForRedis.setOuCode(ouCode); //产权单位
            registrationApplyForRedis.setType(type);   //充电桩类型
            registrationApplyForRedis.setNote(note);  //申请备注
            registrationApplyForRedis.setOrderId(orderId);   //运维系统传递来的编号，用于后续注册码查询
            registrationApplyForRedis.setVendorName(vendorName);    //生产厂家
            registrationApplyForRedis.setEquipModel(equipModel);    //设备型号
            registrationApplyForRedis.setChargerFeeModelId(chargerfeemodel.getId());    //电费模型
            registrationApplyForRedis.setServiceFeeModelId(servicefeemodel.getId());    //服务费模型
            registrationApplyForRedis.setCreatorUuid(user.getUuid());   //创建人
            registrationApplyForRedis.setCreatedAt(new Date());// 创建时间
            registrationApplyRedisService.addApplyInfoToRedis(registrationApplyForRedis,RegistrationForRedisEnum.REGISTRATION_FOR_REDIS);

            /*****end 功能描述:将 注册码申请信息保存到redis里面  author:zhangMumu edit 2018/4/3 0003 11:27*****/

            return new ResponseBase(0, "");
        } catch (Exception e){
            logger.error(e.getLocalizedMessage());
            //  错误代码 40000  错误内容 方法报错
            return new ResponseBase(HsfError.ERROR_CODE_FUNCTION_ERROR, HsfError.ERROR_MSG_FUNCTION_ERROR) ;
        }
    }

    /**
     * 根据桩注册码获取桩信息
     *
     * @param registerCode - 注册码
     * @param stakeNo - 桩编号，新桩注册全为 0， 老桩重新注册为桩编号
     * @return
     */
    @Override
    public ResponseStake getStakeByRegisterCode(String registerCode, String stakeNo) {
        try{
            ResponseStake rs = new ResponseStake(0, "");

            if(registerCode==null || registerCode.trim().length()==0){
                logger.warn("StakeServiceImpl-->getStakeByRegisterCode : 注册码编号不能为空!");
                rs.setErrCode(HsfError.ERROR_CODE_BAD_PARAMETER);
                rs.setErrMsg(HsfError.ERROR_MSG_BAD_PARAMETER);
                return rs;
            }


            //验证注册码
            BaseRegistration registration = baseRegistrationService.getRegistrationByNumber(registerCode);
            if (registration==null){
                logger.warn("StakeServiceImpl-->getStakeByRegisterCode : 根据注册码"+registerCode+"没有查到对应的注册码信息!");
                rs.setErrCode(HsfError.ERROR_CODE_NO_SUCH_REGISTER_CODE);
                rs.setErrMsg(HsfError.ERROR_MSG_NO_SUCH_REGISTER_CODE);
                return rs;
            }

            //验证注册码申请
            BaseRegistrationApply baseRegistrationApply = baseRegistrationApplyService.getBaseRegistrationApply(registration.getRegistrationapplyuuid());
            if (null == baseRegistrationApply) {
                logger.warn("StakeServiceImpl-->getStakeByRegisterCode : 根据注册码主键"+registration.getUuid()+"没有查到对应的注册码申请信息!");
                rs.setErrCode(HsfError.ERROR_CODE_NO_SUCH_REGISTRATION_APPLY);
                rs.setErrMsg(HsfError.ERROR_MSG_NO_REGISTRATION_APPLY);
                return rs;
            }

            //验证组织机构
            SyncOrganization syncOrganization = syncOrganizationService.get(baseRegistrationApply.getProrgcode());
            if (syncOrganization == null || syncOrganization.getStandardcode()==null || syncOrganization.getStandardcode().trim().length()==0){
                logger.warn("StakeServiceImpl-->getStakeByRegisterCode :根据组织机构编码"+baseRegistrationApply.getProrgcode()+"没有找到组织机构!");
                rs.setErrCode(HsfError.ERROR_CODE_NO_SUCH_ORG) ;
                rs.setErrMsg(HsfError.ERROR_MSG_NO_SUCH_ORG) ;
                return rs;
            }

            BaseStakeCriteria param = new BaseStakeCriteria();
            //桩编号不为空并且为老桩编码时带上桩编码一起查询
            if(StringUtils.isNotBlank(stakeNo) && !BasicDataRedisConstants.INIT_STAKE_NO.equals(stakeNo)){
                param.setStakeno(stakeNo);
            }
            param.setRegistrationuuid(registration.getUuid());
            List stakeList = baseStakeService.queryStake(param);

            //注册码未被使用并且标记为新桩才继续处理
            if(CollectionUtils.isNotEmpty(stakeList)){
                logger.warn("StakeServiceImpl-->getStakeByRegisterCode :注册码已经被使用"+registration.getNumber());
                rs.setErrCode(HsfError.ERROR_CODE_REGISTER_CODE_USED) ;
                rs.setErrMsg(HsfError.ERROR_MSG_REGISTER_CODE_USED) ;
                return rs;
            }


            BaseStake stake = new BaseStake();
            stake.setStakeno(BasicDataRedisConstants.INIT_STAKE_NO);
            /*prOrgCode该字段存入到了站表中*/
            /*厂家与型号 由于运维app并没有传值进来,就不做处理了*/
                /*BaseVendorInfoCriteria vendorInfoCriteria = new BaseVendorInfoCriteria();
                vendorInfoCriteria.setName(baseRegistrationApply.getEquipmodel());
                BaseVendorInfo baseVendor = baseVendorInfoService.getVendorByParams(vendorInfoCriteria);
                if (baseVendor!=null){
                    stake.setVendoruuid(baseVendor.getUuid()); //生产厂家主键
                }
                BaseEquipmentInfoCriteria equipmentInfoCriteria = new BaseEquipmentInfoCriteria();
                equipmentInfoCriteria.setType(baseRegistrationApply.getStaketype()+"");
                equipmentInfoCriteria.setVendoruuid(baseRegistrationApply.getVendorname());
                BaseEquipmentInfo baseEquipment = baseEquipmentInfoService.getEquipmentByParams(equipmentInfoCriteria);
                if (baseEquipment!=null) {
                    stake.setEquipmodeluuid(baseEquipment.getUuid());// 设备型号主键
                }*/
            stake.setCreatoruuid(baseRegistrationApply.getCreatoruuid());
            stake.setIsthird(0);
            stake.setStakestatus(BasicDataRedisConstants.STATION_STATUS_TRIAL);
            stake.setType(baseRegistrationApply.getStaketype());
            stake.setRegistrationuuid(registration.getUuid());
            stake.setStatus(Consts.STATUS_NORMAL);
            stake.setCreatedat(new Date());
            baseStakeService.saveStake(stake, BussinessTypeEnum.TRACE_TYPE.WORKORDER,registration.getUuid());

            registration.setStatus(StakeConsts.REGISTRACTION_STATUS_REGEISTED);//修改注册码状态
            baseRegistrationService.updateBySelective(registration);

            //发送 MQ 通知检修此注册码已经被使用了
            if (!basePropService.isLocal()){
                mqService.sendMessage(StakeConsts.MQ_TOPIC_REGISTRATIO, "REGIST", registration.getNumber(),registration.getUuid(),BussinessTypeEnum.MQ_BUSINESS_TYPE.REGISTRACTIONAPPLY);
            }

            return rs ;
        }catch (Exception e){
            logger.error(e.getLocalizedMessage());
            //  错误代码 40000  错误内容 方法报错
            return new ResponseStake(HsfError.ERROR_CODE_FUNCTION_ERROR, HsfError.ERROR_MSG_FUNCTION_ERROR) ;
        }
    }


    /**
     * 根据注册码获取桩编号和授权码
     * @param registerCode 注册码
     * @param fingerprint 设备指纹
     * @return
     */
    @Override
    public ResponseStake genStakeNoAndAuthCode(String registerCode, String fingerprint) {
        try{

            ResponseStake rs = new ResponseStake(0, "");

            if(StringUtils.isBlank(registerCode)){
                logger.warn("StakeServiceImpl-->getStakeByRegisterCode : 注册码编号不能为空!");
                rs.setErrCode(HsfError.ERROR_CODE_BAD_PARAMETER);
                rs.setErrMsg(HsfError.ERROR_MSG_BAD_PARAMETER);
                return rs;
            }

            //验证注册码
            BaseRegistration registration = baseRegistrationService.getRegistrationByNumber(registerCode);
            if (registration==null){
                logger.info("StakeServiceImpl-->getStakeByRegisterCode : 根据注册码"+registerCode+"没有查到对应的注册码信息!");
                rs.setErrCode(HsfError.ERROR_CODE_NO_SUCH_REGISTER_CODE);
                rs.setErrMsg(HsfError.ERROR_MSG_NO_SUCH_REGISTER_CODE);
                return rs;
            }

            //如果注册码存在，则根据注册码查询桩信息
            BaseStakeCriteria stakeCriteria = new BaseStakeCriteria();
            stakeCriteria.setRegistrationuuid(registration.getUuid());//根据注册码主键查找
            BaseStake stake = baseStakeService.getBaseStakeByParams(stakeCriteria);
            if (stake == null) {
                logger.info("gen stake no and auth code not found stake");
                rs.setErrCode(HsfError.ERROR_CODE_NO_SUCH_STAKE);
                rs.setErrMsg(HsfError.ERROR_MSG_NO_SUCH_REGISTER_CODE);
                return rs;
            }

            //验证注册码申请
            BaseRegistrationApply baseRegistrationApply = baseRegistrationApplyService.getBaseRegistrationApply(registration.getRegistrationapplyuuid());
            if (baseRegistrationApply==null){
                logger.info("StakeServiceImpl-->getStakeByRegisterCode : 根据注册码主键"+registration.getUuid()+"没有查到对应的注册码申请信息!");
                rs.setErrCode(HsfError.ERROR_CODE_NO_SUCH_REGISTRATION_APPLY);
                rs.setErrMsg(HsfError.ERROR_MSG_NO_REGISTRATION_APPLY);
                return rs;
            }

            //验证组织机构
            SyncOrganization syncOrganization = syncOrganizationService.get(baseRegistrationApply.getProrgcode());
            if (syncOrganization == null || syncOrganization.getStandardcode()==null || syncOrganization.getStandardcode().trim().length()==0){
                logger.info("StakeServiceImpl-->getStakeByRegisterCode :根据组织机构编码"+baseRegistrationApply.getProrgcode()+"没有找到组织机构!");
                rs.setErrCode(HsfError.ERROR_CODE_NO_SUCH_ORG) ;
                rs.setErrMsg(HsfError.ERROR_MSG_NO_SUCH_ORG) ;
                return rs;
            }


            String stakeNo = stake.getStakeno();
            Boolean older = false;//新桩
            if(StringUtils.isNotBlank(stakeNo) && !BasicDataRedisConstants.INIT_STAKE_NO.equals(stakeNo)){
                older = true;// 老桩
            } else if(BasicDataRedisConstants.INIT_STAKE_NO.equals(stakeNo)){//如果是新桩

                if (StringUtils.isNotBlank(stake.getAuthcode())){//如果授权码不为空
                    // 桩编号 stakeNo 和 授权码 authCode 都不为空，错误
                    rs.setErrCode(HsfError.ERROR_CODE_STAKE_ALREADY_EXISTS);
                    rs.setErrMsg(HsfError.ERROR_MSG_STAKE_ALREADY_EXISTS);
                    return rs;
                }
                // 生成桩编号
                stakeNo = createStakeNo(syncOrganization.getStandardcode());
                if (StringUtils.isBlank(stakeNo)){
                    rs.setErrCode(HsfError.ERROR_CODE_STAKE_NO_CREATE_ERROR);
                    rs.setErrMsg(HsfError.ERROR_MSG_STAKE_NO_CREATE_ERROR);
                    return rs ;
                }
                stake.setStakeno(stakeNo);
                stake.setOutstakeno(stakeNo);
            }

            /*生成授权码*/
            String authCode = "";
            if (basePropService.isLocal()){
                authCode = System.currentTimeMillis() + "";
            }else {
                authCode = baseRegistrationService.genAuthCode(fingerprint, registerCode, stakeNo);//生成授权码
            }
            stake.setAuthcode(authCode); // 给桩添加授权码
            stake.setFingerpint(fingerprint);

            // 绑定桩和服务模型关系  表 base_chargerfeemodel_info
            List<Map<String, String>> modelBindStakeList = new ArrayList<>() ;//计费模型和桩绑定关系集合
            buildBindFeeModelMap(stake.getStakeno(), 1, baseRegistrationApply.getChargerfeemodelcode(),"0",modelBindStakeList);
            buildBindFeeModelMap(stake.getStakeno(), 2, baseRegistrationApply.getServicefeemodelcode(),"0",modelBindStakeList);

            //绑定计费模型，装注册完成重启后会立刻去清分结算请求计费模型，请求不到则提示失败，所以需要在此处为桩绑定计费模型
            boolean b = false;
            if (basePropService.isLocal()){
                b = true;
            }else {
                /*非本地运行,调用接口*/
                commonUtil.sendBindToKeDong(modelBindStakeList, baseRegistrationApply.getProrgcode());// 由于桩表中已经不存在prorgcode，所以此处取的registrationApply表中的字段
            }
            if(!b){
                rs.setErrCode(HsfError.ERROR_CODE_STAKE_BIND_FEEMODEL_FAILED) ;
                rs.setErrMsg(HsfError.ERROR_MSG_STAKE_BIND_FEEMODEL_FAILED) ;
                return rs ;
            }

            int updateFlag = baseStakeService.updateStakeBySelective(stake, BussinessTypeEnum.TRACE_TYPE.HSF,"genStakeNoAndAuthCode");

            // 提示桩接入成功
            if (!basePropService.isLocal()){
                mqService.sendMessage(StakeConsts.MQ_TOPIC_STAKE, StakeConsts.MQ_TAG_STAKE_REGISTE, stake.getUuid(), stake.getStakeno(), BussinessTypeEnum.MQ_BUSINESS_TYPE.STAKE);
            }

            if (older && !basePropService.isLocal()){
                //发送 MQ 通知各组桩接入成功（老桩注册）
                mqService.sendMessage(StakeConsts.MQ_TOPIC_STAKE, StakeConsts.MQ_TAG_STAKE_STAKE_UPDATE, stake.getUuid(),stake.getStakeno(),BussinessTypeEnum.MQ_BUSINESS_TYPE.STAKE) ;
            }
            return rs ;
        }catch (Exception e){
            logger.error(e.getLocalizedMessage());
            //  错误代码 40000  错误内容 方法报错
            return new ResponseStake(HsfError.ERROR_CODE_FUNCTION_ERROR, HsfError.ERROR_MSG_FUNCTION_ERROR) ;
        }
    }


    /**
     * 桩绑定计费模型
     * @param stakeNo
     * @param feetype
     * @param feeModelId
     * @param modelList
     */
    private void buildBindFeeModelMap(String stakeNo,int feetype, String feeModelId,String chargeno,List modelList){
        //todo 计费模型后续需要绑定到枪
        BaseFeeModelRel modelinfo = new BaseFeeModelRel();
        modelinfo.setStakeno(stakeNo);
        modelinfo.setChargerno(chargeno);
        modelinfo.setFeetype(feetype);//电费
        modelinfo.setModeid(feeModelId);
        int saveCModel = baseFeeModelRelService.saveModel(modelinfo);
        if (saveCModel>0){
            Map<String, String> map = new HashMap<>() ;
            map.put("modelId", feeModelId) ;
            map.put("stakeNo", stakeNo) ;
            map.put("chargePort", chargeno) ;
            map.put("serverType", feetype+"") ;
            modelList.add(map);
        }
    }

    /**
     * 根据一期组织机构编码生成桩编号
     * @param orgCode
     * @return
     */
    private String createStakeNo(String orgCode){
        try{

            String fixed = basePropService.getProp(BasePropConstants.stakeNoFixedMiddle);
            if (StringUtils.isEmpty(fixed)) {
                fixed = "900" ;
            }
            if(orgCode.length() > 5){
                orgCode = orgCode.substring(0, 5) ;
            }

            int index = baseStakeOrgIndexService.getStakeIndexByOrgNo(orgCode).intValue();

            BaseStakeOrgIndex stakeIndexByOrgNo = baseStakeOrgIndexService.findByOrgNo(orgCode);
            /*stakeIndexOrgNo不存在则保存一个*/
            if (null == stakeIndexByOrgNo){
                stakeIndexByOrgNo = new BaseStakeOrgIndex();
                stakeIndexByOrgNo.setStandardCode(orgCode);
                stakeIndexByOrgNo.setNoindex(index);
                baseStakeOrgIndexService.save(stakeIndexByOrgNo);

            /*stakeIndexOrgNo存在则更新它*/
            }else {
                stakeIndexByOrgNo.setNoindex(index);
                baseStakeOrgIndexService.updateBySelective(stakeIndexByOrgNo);
            }

            String formatIndex = String.valueOf(index);
            int startLen = formatIndex.length() ;
            if(startLen < 8){
                for(int i = 8; i > startLen; i --){
                    formatIndex = "0" + formatIndex ;
                }
            }
            return orgCode + fixed + formatIndex ;
        }catch (Exception e){
            logger.error("StakeServiceImpl_createStakeNo_"+e.getLocalizedMessage());
            return null;
        }

    }

    /**
     * 检查是否是正常的充电桩
     * @param registerCode 注册码
     * @param authCode 授权码
     * @param fingerprint
     * @return
     *
     * 根据注册码获取注册码主键，不存在则提示失败!
     * 根据注册码主键获取授权码，不存在则提示失败!
     * 如果缓存和数据库中桩的授权码为空，接口参数授权码不为空，则将该授权码缓存到redis
     *
     */
    @IgnoreAopLog
    @Override
    public ResponseBoolean checkStake(String registerCode, String authCode, String fingerprint) {
        Long stime = System.currentTimeMillis();
        logger.info("StakeServiceImpl---->checkStake[registerCode："+registerCode+" == authCode："+authCode+"  == fingerprint："+fingerprint+"]  开始时间："+stime) ;
        ResponseBoolean rb = new ResponseBoolean(0, "", false);

        if (registerCode==null || registerCode.trim().length()==0){
            rb.setErrCode(HsfError.ERROR_CODE_BAD_PARAMETER) ;
            rb.setErrMsg(HsfError.ERROR_MSG_BAD_PARAMETER+"：注册码为空!") ;
            return rb;
        }

        if (authCode==null || authCode.trim().length()==0){
            rb.setErrCode(HsfError.ERROR_CODE_BAD_PARAMETER) ;
            rb.setErrMsg(HsfError.ERROR_MSG_BAD_PARAMETER+"：授权码为空!") ;
            return rb;
        }

        // 验证注册码
        String registrationUuid = baseRegistrationService.getRegistrationUuidByNumber(registerCode);

        if (registrationUuid==null || registrationUuid.trim().length()==0){
            rb.setErrCode(HsfError.ERROR_CODE_NO_SUCH_REGISTER_CODE) ;
            rb.setErrMsg(HsfError.ERROR_MSG_NO_SUCH_REGISTER_CODE) ;
            return rb;
        }

        String stake_authCode = baseStakeService.getAuthCodeByRegUuid(registrationUuid);
        if (stake_authCode==null || stake_authCode.trim().length()==0){

            if(!StringUtils.isEmpty(authCode) && authCode.length() == 50) {
//                redisService.add(stakeKey,authCode);
                //将授权吗和注册码主键放入阻塞队列中，用于异步线程更新数据库
//                    LinkedDequeUtil.getInstance().setStringToDeque(registrationUuid+"&"+authCode);
                rb.setValue(true) ;
                logger.info("check stake auth code true");
            } else {
                logger.info("check stake failed check aut code failed") ;
                rb.setErrCode(HsfError.ERROR_CODE_BAD_PARAMETER) ;
                rb.setErrMsg(HsfError.ERROR_MSG_BAD_PARAMETER) ;
            }

        }else {
            if(stake_authCode.equals(authCode)){
                rb.setValue(true) ;
                logger.info("check stake auth code true");
            } else {
                logger.info("check stake failed auth code error") ;
                rb.setErrCode(HsfError.ERROR_CODE_BAD_PARAMETER) ;
                rb.setErrMsg(HsfError.ERROR_MSG_BAD_PARAMETER) ;
            }
        }



        /**

        String regKey = CreateKeyUtil.getKey("registration",registerCode);//获取key值

        try{
            String registrationUuid = (String) redisService.get(regKey);
            //如果redis中不存在注册码信息，则查询数据库
            if(registrationUuid == null){
                BaseRegistration registrationEntity = baseRegistrationService.getRegistrationByNumber(registerCode);
               //如果数据库中不存在，则返回
                if (registrationEntity == null) {
                    logger.info("check stake failed registration is null") ;
                    rb.setErrCode(HsfError.ERROR_CODE_NO_SUCH_REGISTER_CODE) ;
                    rb.setErrMsg(HsfError.ERROR_MSG_NO_SUCH_REGISTER_CODE) ;
                    return rb;
                }else{
                    String key = CreateKeyUtil.getKey("registration", registrationEntity.getNumber());
                    String uuid = registrationEntity.getUuid();

                    redisService.add(key, uuid);

                    registrationUuid = uuid;
                }
            }

            String stakeKey = CreateKeyUtil.getKey("stakereg_",registrationUuid);

            String stakeValue = (String) redisService.get(stakeKey);
            logger.info("stakeValue---->"+stakeValue);
            //如果redis中不存在authCode，则查询数据库
            if(stakeValue==null){
                BaseStake stake = baseStakeService.getBaseStakeByRegistration(registrationUuid);
                if (stake == null) {
                    logger.info("check stake failed stake not fund ") ;
                    rb.setErrCode(HsfError.ERROR_CODE_NO_SUCH_STAKE) ;
                    rb.setErrMsg(HsfError.ERROR_MSG_NO_SUCH_STAKE) ;
                    return rb;
                }else{
                    String stake_registrationUuid = stake.getRegistrationuuid();
                    String code = stake.getAuthcode();
                    //生成key值
                    String key = CreateKeyUtil.getKey("stakereg_", stake_registrationUuid);

                    redisService.add(key, code);

                    stakeValue = code;
                }
            }

            //如果数据库中authCode为空，则将参数传递过来的authCode添加到redis和持久化到数据库中
            if(StringUtils.isEmpty(stakeValue)){
                logger.info("check stake auth code not exists ") ;
                if(!StringUtils.isEmpty(authCode) && authCode.length() == 50) {

                    redisService.add(stakeKey,authCode);
                    //将授权吗和注册码主键放入阻塞队列中，用于异步线程更新数据库
//                    LinkedDequeUtil.getInstance().setStringToDeque(registrationUuid+"&"+authCode);
                    rb.setValue(true) ;
                    logger.info("check stake auth code true");
                } else {
                    logger.info("check stake failed check aut code failed") ;
                    rb.setErrCode(HsfError.ERROR_CODE_BAD_PARAMETER) ;
                    rb.setErrMsg(HsfError.ERROR_MSG_BAD_PARAMETER) ;
                }
            } else {
                logger.info("check stake auth code exists") ;
                if(stakeValue.equals(authCode)){
                    rb.setValue(true) ;
                    logger.info("check stake auth code true");
                } else {
                    logger.info("check stake failed auth code error") ;
                    rb.setErrCode(HsfError.ERROR_CODE_BAD_PARAMETER) ;
                    rb.setErrMsg(HsfError.ERROR_MSG_BAD_PARAMETER) ;
                }
            }

        }catch (Exception e){
            logger.error(e.getLocalizedMessage());
        }

         **/


        return rb;
    }

    /**
     * 根据UUID获取注册码申请
     * 当申请通过时，会带有注册码数据
     *
     * @param uuid  注册码申请表主键
     * @return 注册码申请实体
     */
    @Override
    public ResponseRegistrationApply getRegistration(String uuid){
        ResponseRegistrationApply responseRegistrationApply = new ResponseRegistrationApply(0, "") ;

        RegistrationApply hsfRegistrationApply = baseRegistrationApplyService.getHsfRegistrationApply(uuid, BasicDataStatus.WORKORDER_STATUS_FINISH.getCode());
        if (hsfRegistrationApply!=null){
            List<Registration> registrations = baseRegistrationService.queryHsfRegistration(hsfRegistrationApply.getUuid());
            hsfRegistrationApply.getRegistrations().addAll(registrations);
        }

        responseRegistrationApply.setRegistrationApply(hsfRegistrationApply) ;

        return responseRegistrationApply ;
    }

    /**
     * 根据桩编号获取桩信息
     * @param stakeNo 桩编号
     * @return 桩实体
     */
    @Override
    public ResponseStake getStakeByNo(String stakeNo){
        ResponseStake rs = new ResponseStake(0, "");
        Stake stake = baseStakeService.getStakeHSF(stakeNo);
        rs.setStake(stake);
        return rs;
    }


    /**
     * 桩变动接收确认
     *
     * @param stakeNo
     * @param confirm
     * @return
     */
    @Override
    public ResponseBase confirmStakeChange(String stakeNo, int confirm){
        logger.debug("get stake change confirm stakeNo = " + stakeNo + " confirmed = " + confirm); ;
//        Entity changeLog = dbSession.queryOneRawSql("stakeChangeLog",
//            "(oldStakeNo=? or newStakeNo=?) and status=?",
//            new Object[]{stakeNo, stakeNo, Consts.STATUS_NORMAL}) ;
//        if(changeLog == null){
//            return new ResponseBase(HsfError.ERROR_CODE_NO_SUCH_CHANGELOG, HsfError.ERROR_MSG_NO_SUCH_CHANGELOG) ;
//        }
//
//        changeLog.setValue("confirmed", confirm) ;
//        if(confirm == 0){
//            changeLog.setValue("status", Consts.STATUS_DELETED) ;
//        }
//        dbSession.save(changeLog) ;
        return new ResponseBase(0, "") ;
    }

    /**
     * 获取桩(编号、授权码)变动记录
     *
     * @param changeLogUuid
     * @return
     */
    @Override
    public ResponseStakeChangeLog getChangeLog(String changeLogUuid){
//        Entity changeLog = dbSession.getEntity("stakeChangeLog", changeLogUuid) ;
//        if(changeLog == null){
//            return new ResponseStakeChangeLog(HsfError.ERROR_CODE_NO_SUCH_CHANGELOG, HsfError.ERROR_MSG_NO_SUCH_CHANGELOG) ;
//        }
//
//        Entity stake = changeLog.sr(dbSession, "stake") ;
//        if(stake == null){
//            return new ResponseStakeChangeLog(HsfError.ERROR_CODE_NO_SUCH_STAKE, HsfError.ERROR_MSG_NO_SUCH_STAKE) ;
//        }

        ResponseStakeChangeLog responseStakeChangeLog = new ResponseStakeChangeLog(0, "") ;
//        StakeChangeLog log = changeLog.looksLike(StakeChangeLog.class) ;
//        Stake s = stake.looksLike(Stake.class) ;
//        Entity registration = stake.sr(dbSession, "registration") ;
//        if(registration != null){
//            s.setRegistration(registration.looksLike(Registration.class)) ;
//        }
//        log.setStake(s) ;
//        responseStakeChangeLog.setStakeChangeLog(log) ;

        return responseStakeChangeLog ;
    }


    @Override
    public boolean initRedis(){
        return true;
    }

    /**
     *  初始化桩信息到redis中
     * @return
     */
    @Override
    public boolean initStakeInRedis(){
        return true;
    }
}
